home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 6 code / TCP / NewsWatcher / NW Source / Source / ldef.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-05  |  9.9 KB  |  380 lines  |  [TEXT/MMCC]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     ldef.c
  4.  
  5.     This module contains the LDEF for NewsWatcher.
  6.     
  7.     Copyright © 1994-1995, Northwestern University.
  8.  
  9. ----------------------------------------------------------------------------*/
  10.  
  11. #include <string.h>
  12.  
  13. #include "glob.h"
  14. #include "ldef.h"
  15. #include "header.h"
  16. #include "drawutil.h"
  17. #include "windutil.h"
  18. #include "memutil.h"
  19.  
  20. static RGBColor gLightBlue = {0x9999, 0x9999, 0xFFFF};    /* light blue for filling triangles */
  21.  
  22. static Rect gRect;                    /* cell rect */
  23. static FontInfo gFontInfo;            /* font information */
  24. static TWindow **gInfo;                /* window information */
  25. static short gIndex;                /* index in group or subject array */
  26. static Handle gStrings;                /* handle to strings */
  27. static short gH, gV;                /* h and v coords for drawing */
  28. static Rect gEraseRect;                /* rectangle erased and redrawn */
  29. static TSubject **gSubjectArray;     /* handle to subject array */
  30. static TSubject gTheSubject;        /* subject record to be drawn */
  31. static short gRow;                    /* row number of cell being drawn */
  32. static ListHandle gTheList;            /* handle to list record */
  33. static short gRightEdge;            /* right cell edge minus indentation */
  34.  
  35.  
  36.  
  37. /* The following global variable is exported. */
  38.  
  39. ListDefUPP gListDefFuncUPP = nil;
  40.  
  41.  
  42.  
  43. /*----------------------------------------------------------------------------
  44.     DrawFullOrNewGroupCell
  45.     
  46.     Draw a single cell in the full group list window or the new groups
  47.     list window.
  48. ----------------------------------------------------------------------------*/
  49.  
  50. static void DrawFullOrNewGroupCell (void)
  51. {            
  52.     TGroup **groupArray;
  53.     Str255 str;
  54.     
  55.     groupArray = (**gInfo).groupArray;
  56.     gEraseRect = gRect;
  57.     EraseRect(&gEraseRect);
  58.     strcpy((char*)str, *gStrings + (*groupArray)[gIndex].nameOffset);
  59.     c2pstr((char*)str);
  60.     TruncString(gRightEdge - gH, str, smTruncEnd);
  61.     MoveTo(gH, gV);
  62.     DrawString(str);
  63. }
  64.  
  65.  
  66.  
  67. /*----------------------------------------------------------------------------
  68.     DrawUserGroupCell
  69.     
  70.     Draw a single cell in a user group list window.
  71. ----------------------------------------------------------------------------*/
  72.  
  73. static void DrawUserGroupCell (void)
  74. {            
  75.     TGroup **groupArray, theGroup;
  76.     long numUnread;
  77.     Str255 str;
  78.     short h;
  79.  
  80.     groupArray = (**gInfo).groupArray;
  81.     theGroup = (*groupArray)[gIndex];
  82.     gEraseRect = gRect;
  83.     if (theGroup.onlyRedrawCount) gEraseRect.right = gH + (**gInfo).numUnreadHCoord;
  84.     EraseRect(&gEraseRect);
  85.     numUnread = theGroup.numUnread;
  86.     if (numUnread != 0) {
  87.         if (numUnread > 9999) numUnread = 9999;
  88.         NumToString(numUnread, str);
  89.         MoveTo(gH + (**gInfo).numUnreadHCoord - StringWidth(str), gV);
  90.         DrawString(str);
  91.     }
  92.     if (!theGroup.onlyRedrawCount) {
  93.         strcpy((char*)str, *gStrings + theGroup.nameOffset);
  94.         c2pstr((char*)str);
  95.         h = gH + (**gInfo).groupNameHCoord;
  96.         TruncString(gRightEdge - h, str, smTruncEnd);
  97.         MoveTo(h, gV);
  98.         DrawString(str);
  99.     }
  100. }
  101.  
  102.  
  103.  
  104. /*----------------------------------------------------------------------------
  105.     DrawThreadHeadInfo
  106.     
  107.     Draw the thread head info for a thread head cell in a subject list 
  108.     window (the thread control and number of articles in the thread).
  109. ----------------------------------------------------------------------------*/
  110.  
  111. static void DrawThreadHeadInfo (void)
  112. {
  113.     PolyHandle poly;
  114.     short th, tv;
  115.     Str255 str;
  116.     short threadLength;
  117.  
  118.     if (gTheSubject.threadLength == 1) {
  119.         MoveTo(gH + (**gInfo).minusSignHCoord, gV);
  120.         DrawChar('-');
  121.     } else {
  122.         if (gTheSubject.collapsed) {
  123.             poly = (**gInfo).collapseTriangle;
  124.             th = gH + ((**poly).polyBBox.right >> 1) + 1; 
  125.             tv = gRect.top + 1;
  126.         } else {
  127.             poly = (**gInfo).expandTriangle;
  128.             th = gH + 1; 
  129.             tv = gRect.top + ((**poly).polyBBox.bottom >> 1) + 1;
  130.         }
  131.         OffsetPoly(poly, th, tv);
  132.         if (gTheSubject.drawTriangleFilled) {
  133.             FillPoly(poly, &qd.black);
  134.         } else {
  135.             FillColorPoly(poly, &gLightBlue, &qd.gray);
  136.         }
  137.         FramePoly(poly);
  138.         OffsetPoly(poly, -th, -tv);
  139.  
  140.         if (!gTheSubject.onlyRedrawTriangle) {
  141.             threadLength = gTheSubject.threadLength;
  142.             if (threadLength > 99) threadLength = 99;
  143.             NumToString(threadLength, str);
  144.             MoveTo(gH + (**gInfo).threadCountHCoord - StringWidth(str), gV);
  145.             DrawString(str);
  146.         }
  147.     }
  148. }
  149.  
  150.  
  151.  
  152. /*----------------------------------------------------------------------------
  153.     DrawCheckMark
  154.     
  155.     Draw the article read check mark in a cell in a subject list window.
  156.     For collapsed thread head cells, the mark is drawn iff the entire
  157.     thread has been read. 
  158. ----------------------------------------------------------------------------*/
  159.  
  160. static void DrawCheckMark (void)
  161. {
  162.     Boolean read;
  163.     short nextInThread;
  164.     TextStyle savedStyle;
  165.  
  166.     if (gTheSubject.collapsed) {
  167.         read = true;
  168.         nextInThread = gIndex;
  169.         while (true) {
  170.             if (!(*gSubjectArray)[nextInThread].read) {
  171.                 read = false;
  172.                 break;
  173.             }
  174.             nextInThread = 
  175.                 (*gSubjectArray)[nextInThread].nextInThread;
  176.             if (nextInThread == -1) break;
  177.         }
  178.     } else {
  179.         read = gTheSubject.read;
  180.     }
  181.     if (read) {
  182.         GetPortTextStyle(&savedStyle);
  183.         TextFont(systemFont);
  184.         MoveTo(gH + (**gInfo).checkHCoord, gV);
  185.         DrawChar(checkMark);
  186.         SetPortTextStyle(&savedStyle);
  187.     } else if (gTheSubject.incomplete) {
  188.         MoveTo(gH + (**gInfo).checkHCoord, gV);
  189.         DrawChar('<');
  190.     } else if (gTheSubject.complete) {
  191.         MoveTo(gH + (**gInfo).checkHCoord, gV);
  192.         DrawChar('•');
  193.     }
  194. }
  195.  
  196.  
  197.  
  198. /*----------------------------------------------------------------------------
  199.     DrawAuthorAndSubject
  200.     
  201.     Draw the author and subject in a cell in a subject list window.
  202. ----------------------------------------------------------------------------*/
  203.  
  204. static void DrawAuthorAndSubject (void)
  205. {
  206.     Str255 str;
  207.     short h;
  208.  
  209.     if ((**gInfo).authorsShown && gTheSubject.authorOffset >= 0) {
  210.         strcpy((char*)str, *gStrings + gTheSubject.authorOffset);
  211.         FormatAuthorName((char*)str);
  212.         c2pstr((char*)str);
  213.         TruncString((**gInfo).authorWidth, str, smTruncEnd);
  214.         MoveTo(gH + (**gInfo).authorHCoord, gV);
  215.         DrawString(str);
  216.     }
  217.     strcpy((char*)str, *gStrings + gTheSubject.subjectOffset);
  218.     c2pstr((char*)str);
  219.     h = gH + (**gInfo).subjectHCoord;
  220.     TruncString(gRightEdge - h, str, smTruncEnd);
  221.     MoveTo(h, gV);
  222.     DrawString(str);
  223. }
  224.  
  225.  
  226.  
  227. /*----------------------------------------------------------------------------
  228.     DrawSubjectCell
  229.     
  230.     Draw a single cell in a subject list window.
  231. ----------------------------------------------------------------------------*/
  232.  
  233. static void DrawSubjectCell (void)
  234. {    
  235.     gSubjectArray = (**gInfo).subjectArray;
  236.     gTheSubject = (*gSubjectArray)[gIndex];
  237.     gEraseRect = gRect;
  238.     if (gTheSubject.onlyRedrawTriangle) {
  239.         gEraseRect.right = gH + gFontInfo.ascent + 2;
  240.     } else if (gTheSubject.onlyRedrawCheck) {
  241.         gEraseRect.left = gH + (**gInfo).checkHCoord;
  242.         gEraseRect.right = gH + (**gInfo).authorHCoord;
  243.     }
  244.     EraseRect(&gEraseRect);
  245.  
  246.     if (gTheSubject.threadOrdinal == 1 && !gTheSubject.onlyRedrawCheck) 
  247.         DrawThreadHeadInfo();
  248.     
  249.     if (!gTheSubject.onlyRedrawTriangle) 
  250.         DrawCheckMark();
  251.         
  252.     if (!gTheSubject.onlyRedrawTriangle && !gTheSubject.onlyRedrawCheck) 
  253.         DrawAuthorAndSubject();
  254. }
  255.  
  256.  
  257.  
  258. /*----------------------------------------------------------------------------
  259.     HiliteCell
  260.     
  261.     Hilite the cell.
  262. ----------------------------------------------------------------------------*/
  263.  
  264. static void HiliteCell (void)
  265. {
  266.     short pnMode;
  267.     Rect visible;
  268.     Boolean hasColorQD;
  269.     unsigned char hiliteMode;
  270.  
  271.     hasColorQD = HasColorQD();
  272.     if ((**gTheList).lActive && ((WindowPeek)qd.thePort)->hilited) {
  273.         if (hasColorQD) {
  274.             hiliteMode = LMGetHiliteMode();
  275.             BitClr(&hiliteMode, pHiliteBit);
  276.             LMSetHiliteMode(hiliteMode);
  277.         }
  278.         InvertRect(&gEraseRect);
  279.     } else {
  280.         visible = (**gTheList).visible;
  281.         pnMode = qd.thePort->pnMode;
  282.         if (hasColorQD) PenMode(50 + pnMode);
  283.         ClipRect(&gEraseRect);
  284.         MoveTo(gRect.left + 3, gRect.top);
  285.         LineTo(gRect.left + 3, gRect.bottom - 1);
  286.         MoveTo(gRect.right - 4, gRect.top);
  287.         LineTo(gRect.right - 4, gRect.bottom - 1);
  288.         if (gRow == visible.top || (**gTheList).cellArray[gRow-1] >= 0) {
  289.             MoveTo(gRect.left + 4, gRect.top);
  290.             LineTo(gRect.right - 5, gRect.top);
  291.         }
  292.         if (gRow == visible.bottom - 1 || (**gTheList).cellArray[gRow+1] >= 0) {
  293.             MoveTo(gRect.left + 4, gRect.bottom - 1);
  294.             LineTo(gRect.right - 5, gRect.bottom - 1);
  295.         }
  296.         ClipRect(&gRect);
  297.         PenMode(pnMode);
  298.     }
  299. }
  300.  
  301.  
  302.  
  303. /*----------------------------------------------------------------------------
  304.     ListDefFunc
  305.     
  306.     This is the list definition function used for group and subject list 
  307.     windows. It is called by the stub code in the standalone LDEF 128 code 
  308.     resource.
  309. ----------------------------------------------------------------------------*/
  310.  
  311. static pascal void ListDefFunc (short lMessage, Boolean lSelect, Rect *lRect, Cell lCell,
  312.     short lDataOffset, short lDataLen, ListHandle lHandle)
  313. {    
  314.     char *cellDataPtr;
  315.     TWindowKind kind;
  316.     Boolean selected;
  317.     
  318.     if (lMessage != lDrawMsg && lMessage != lHiliteMsg) return;
  319.     
  320.     selected = ((**lHandle).cellArray)[lCell.v] < 0;
  321.     gRect = *lRect;
  322.     gRow = lCell.v;
  323.     gTheList = lHandle;
  324.     gRightEdge = gRect.right - (**lHandle).indent.h;
  325.     
  326.     if (lMessage == lHiliteMsg && (**gTheList).lActive && 
  327.         ((WindowPeek)qd.thePort)->hilited)
  328.     {
  329.         gEraseRect = gRect;
  330.         HiliteCell();
  331.         return;
  332.     }
  333.       
  334.     (**lHandle).port->txFace = 0;
  335.     GetFontInfo(&gFontInfo);
  336.     gH = lRect->left + (**lHandle).indent.h;
  337.     gV = lRect->top + gFontInfo.ascent;
  338.     gInfo = (TWindow**)GetWRefCon((WindowPtr)(**lHandle).port);
  339.     kind = (**gInfo).kind;
  340.     if (kind == kSubject) {
  341.         gStrings = (**gInfo).strings;
  342.     } else {
  343.         gStrings = gGroupNames;
  344.     }
  345.     cellDataPtr = *(**lHandle).cells + lDataOffset;
  346.     gIndex = *(unsigned short*)cellDataPtr;
  347.     
  348.     switch (kind) {
  349.         case kGroup:
  350.             switch ((**gInfo).groupKind) {
  351.                 case kFullGroup:
  352.                 case kNewGroup:
  353.                     DrawFullOrNewGroupCell();
  354.                     break;
  355.                 case kUserGroup:
  356.                     DrawUserGroupCell();
  357.                     break;
  358.             }
  359.             break;
  360.         case kSubject:
  361.             DrawSubjectCell();
  362.             break;
  363.     }
  364.  
  365.     if (selected) HiliteCell();
  366. }
  367.  
  368.  
  369.  
  370. /*----------------------------------------------------------------------------
  371.     ldef_InitUPP
  372.     
  373.     Initialize UPPs.
  374. ----------------------------------------------------------------------------*/
  375.  
  376. void ldef_InitUPP (void)
  377. {
  378.     gListDefFuncUPP = NewListDefProc(ListDefFunc);
  379. }
  380.